package edu.corn.job.core.engine;

import edu.corn.job.core.context.JobRunningContext;
import edu.corn.job.core.statemachine.JobEventEnum;
import edu.corn.job.core.statemachine.JobStateEnum;
import edu.corn.statemachine.core.Action;
import lombok.AllArgsConstructor;

import static edu.corn.job.core.constant.JobConstants.JOB_MASTER_ID;
import static edu.corn.job.core.constant.JobConstants.JOB_RUNNER;

@AllArgsConstructor
public class JobOptionFactory {


    JobEngine jobEngine;

    /**
     * 外部提交任务时，会触发此action，将任务提交到waiting队列。
     *
     * @return
     */
    public Action<JobStateEnum, JobEventEnum> submitNew2WaitingAction() {
        return context -> {
            JobRunningContext jobContext = (JobRunningContext) context.getSubject();
            jobEngine.getWaitingList().add(jobContext);
            jobEngine.getPendingList().remove(jobContext);
            jobContext.setState(JobStateEnum.RUNNABLE);
            jobEngine.notifyWorker();
        };
    }


    /**
     * 提交任务后会唤醒工作线程，将job提交到线程池。
     *
     * @return
     */
    public Action<JobStateEnum, JobEventEnum> submitWaiting2RunningAction() {
        return context -> {
            JobRunningContext jobContext = (JobRunningContext) context.getSubject();
            if (jobContext != null) {
                JobRunner jobRunner = new JobRunner(jobContext);
                // 将jobContext放入 context中。
                context.putParam(JOB_RUNNER, jobRunner);


                // 将呈递job到线程池的操作交由子类，此时已经封装好了runner类，可以直接被线程池运行。
                jobEngine.submitJob(jobRunner);


                jobContext.setState(JobStateEnum.RUNNABLE);
                jobEngine.getRunningSet().put((String) jobContext.getParam(JOB_MASTER_ID), jobRunner);
            }
        };
    }

    /**
     * 将job从waiting队列转移至pending队列。
     * @return
     */
    public Action<JobStateEnum, JobEventEnum> submitWaiting2PendingAction() {
        return context -> {
            JobRunningContext jobContext = (JobRunningContext) context.getSubject();
            jobEngine.getRunningSet().remove((String) jobContext.getParam(JOB_MASTER_ID));
            jobEngine.getPendingList().add(jobContext);
            jobContext.setState(JobStateEnum.PENDING);
        };
    }

}
